package com.d.common.aspect;

import com.d.common.utils.RT;
import com.d.common.utils.RedisUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * 防止重复提交操作AOP类
 * @author
 * @version
 */
@Aspect
@Component
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class PreventRepetitionAspect {
	private static final String PARAM_TOKEN = "token";

    private static final Logger logger = LoggerFactory.getLogger(PreventRepetitionAspect.class);

    /**
	 * around
	 * @throws Throwable
	 */
	@Around(value = "@annotation(com.d.common.annotation.PreventRepetitionAnnotation)")
	public Object excute(ProceedingJoinPoint joinPoint) throws Throwable{
		try {
			Object result = null;
			ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
			HttpServletRequest request = requestAttributes.getRequest();
			String uri = request.getRequestURI();
			HttpSession session = request.getSession();
			result = validation(joinPoint, request, session, uri.substring(uri.lastIndexOf('/')+1));
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return RT.error(9000, "执行防止重复提交功能AOP失败，原因：" + e.getMessage());
		}
	}

//	public Object generate(ProceedingJoinPoint joinPoint, HttpServletRequest request, HttpSession session,String tokenFlag) throws Throwable {
//		String uuid = UUID.randomUUID().toString();
//		request.setAttribute(PARAM_TOKEN, uuid);
//		return joinPoint.proceed();
//    }

	public Object validation(ProceedingJoinPoint joinPoint, HttpServletRequest request, HttpSession session,String tokenFlag) throws Throwable {
		String requestFlag = request.getParameter(PARAM_TOKEN);
		//redis加锁
		boolean lock = RedisUtil.tryGetDistributedLock(tokenFlag + requestFlag, requestFlag, 5000);
		//System.out.println("lock:" + lock + "," + Thread.currentThread().getName());
		if(lock){
			//加锁成功
			//执行方法
			Object funcResult = joinPoint.proceed();
			//方法执行完之后进行解锁
			RedisUtil.releaseDistributedLock(tokenFlag + requestFlag, requestFlag);
			return funcResult;
		}else{
			//锁已存在
			return RT.error(9000, "不能重复提交！");
		}
    }
}
